using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Text.Json;
using StackExchange.Redis;
using JGSY.CMS.LowCode.Platform.Application.Interfaces;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Services.Cache.Enhanced
{
    /// <summary>
    /// 增强型分层缓存服务
    /// 结合本地内存缓存和分布式缓存，提供自动降级和故障转移
    /// </summary>
    public class HybridCacheService : ICacheService
    {
        private readonly IMemoryCache _memoryCache;
        private readonly ICacheService _distributedCache;
        private readonly ILogger<HybridCacheService> _logger;
        private readonly HybridCacheOptions _options;
        private readonly JsonSerializerOptions _jsonOptions;

        // 缓存统计
        private long _memoryHits = 0;
        private long _distributedHits = 0;
        private long _misses = 0;

        public HybridCacheService(
            IMemoryCache memoryCache,
            ICacheService distributedCache,
            ILogger<HybridCacheService> logger,
            HybridCacheOptions? options = null)
        {
            _memoryCache = memoryCache;
            _distributedCache = distributedCache;
            _logger = logger;
            _options = options ?? new HybridCacheOptions();
            _jsonOptions = new JsonSerializerOptions 
            { 
                PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                WriteIndented = false
            };
        }

        /// <summary>
        /// 分层缓存设置
        /// </summary>
        public async Task SetAsync<T>(string key, T value, TimeSpan? ttl = null)
        {
            var cacheExpiry = ttl ?? _options.DefaultExpiry;
            var memoryExpiry = TimeSpan.FromMilliseconds(Math.Min(cacheExpiry.TotalMilliseconds, _options.MemoryMaxExpiry.TotalMilliseconds));

            try
            {
                // 1. 设置本地内存缓存（快速访问）
                var memoryCacheOptions = new MemoryCacheEntryOptions
                {
                    AbsoluteExpirationRelativeToNow = memoryExpiry,
                    Priority = CacheItemPriority.Normal,
                    Size = EstimateSize(value) // 估算对象大小
                };

                _memoryCache.Set(GetMemoryKey(key), value, memoryCacheOptions);

                // 2. 设置分布式缓存（持久化和共享）
                if (_options.EnableDistributedCache)
                {
                    try
                    {
                        await _distributedCache.SetAsync(key, value, cacheExpiry);
                    }
                    catch (Exception ex)
                    {
                        _logger.LogWarning(ex, "分布式缓存设置失败，仅使用内存缓存: {Key}", key);
                    }
                }

                _logger.LogDebug("缓存设置成功: {Key}, TTL: {TTL}", key, cacheExpiry);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "缓存设置失败: {Key}", key);
                throw;
            }
        }

        /// <summary>
        /// 分层缓存获取
        /// </summary>
    public async Task<T?> GetAsync<T>(string key)
        {
            try
            {
                // 1. 首先检查本地内存缓存
        if (_memoryCache.TryGetValue(GetMemoryKey(key), out var obj) && obj is T memoryValue)
                {
                    Interlocked.Increment(ref _memoryHits);
                    _logger.LogDebug("内存缓存命中: {Key}", key);
                    return memoryValue;
                }

                // 2. 检查分布式缓存
                if (_options.EnableDistributedCache)
                {
                    try
                    {
                        var distributedValue = await _distributedCache.GetAsync<T>(key);
                        if (distributedValue != null)
                        {
                            Interlocked.Increment(ref _distributedHits);
                            _logger.LogDebug("分布式缓存命中: {Key}", key);

                            // 回写到内存缓存
                            await BackfillMemoryCache(key, distributedValue);
                            return distributedValue;
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogWarning(ex, "分布式缓存获取失败: {Key}", key);
                    }
                }

                // 3. 缓存未命中
                Interlocked.Increment(ref _misses);
                _logger.LogDebug("缓存未命中: {Key}", key);
                return default(T);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "缓存获取失败: {Key}", key);
                return default(T);
            }
        }

        /// <summary>
        /// 缓存移除
        /// </summary>
        public async Task RemoveAsync(string key)
        {
            try
            {
                // 移除内存缓存
                _memoryCache.Remove(GetMemoryKey(key));

                // 移除分布式缓存
                if (_options.EnableDistributedCache)
                {
                    try
                    {
                        await _distributedCache.RemoveAsync(key);
                    }
                    catch (Exception ex)
                    {
                        _logger.LogWarning(ex, "分布式缓存移除失败: {Key}", key);
                    }
                }

                _logger.LogDebug("缓存移除成功: {Key}", key);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "缓存移除失败: {Key}", key);
            }
        }

        /// <summary>
        /// 获取缓存统计
        /// </summary>
        public CacheStatistics GetStatistics()
        {
            var total = _memoryHits + _distributedHits + _misses;
            return new CacheStatistics
            {
                MemoryHits = _memoryHits,
                DistributedHits = _distributedHits,
                Misses = _misses,
                TotalRequests = total,
                HitRate = total > 0 ? (double)(_memoryHits + _distributedHits) / total : 0,
                MemoryHitRate = total > 0 ? (double)_memoryHits / total : 0
            };
        }

        #region 私有方法

        private string GetMemoryKey(string key)
        {
            return $"mem:{key}";
        }

        private Task BackfillMemoryCache<T>(string key, T value)
        {
            try
            {
                var memoryCacheOptions = new MemoryCacheEntryOptions
                {
                    AbsoluteExpirationRelativeToNow = _options.MemoryBackfillExpiry,
                    Priority = CacheItemPriority.Normal,
                    Size = EstimateSize(value)
                };

                _memoryCache.Set(GetMemoryKey(key), value, memoryCacheOptions);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "内存缓存回写失败: {Key}", key);
            }
            return Task.CompletedTask;
        }

        private int EstimateSize<T>(T value)
        {
            try
            {
                if (value == null) return 1;
                
                // 简单的大小估算
                if (value is string str)
                    return str.Length * 2; // Unicode字符

                if (value.GetType().IsPrimitive)
                    return 8; // 基本类型

                // 对象类型，尝试序列化估算
                var json = JsonSerializer.Serialize(value, _jsonOptions);
                return json.Length * 2;
            }
            catch
            {
                return 1024; // 默认1KB
            }
        }

        #endregion
    }

    /// <summary>
    /// 缓存预热服务
    /// </summary>
    public class CacheWarmupService
    {
        private readonly ICacheService _cacheService;
        private readonly ILogger<CacheWarmupService> _logger;
        private readonly IServiceProvider _serviceProvider;

        public CacheWarmupService(
            ICacheService cacheService,
            ILogger<CacheWarmupService> logger,
            IServiceProvider serviceProvider)
        {
            _cacheService = cacheService;
            _logger = logger;
            _serviceProvider = serviceProvider;
        }

        /// <summary>
        /// 执行缓存预热
        /// </summary>
        public async Task WarmupAsync()
        {
            _logger.LogInformation("开始缓存预热");

            try
            {
                var warmupTasks = new List<Task>
                {
                    WarmupWorkflowDataAsync(),
                    WarmupTemplateDataAsync(),
                    WarmupConfigDataAsync(),
                    WarmupUserDataAsync()
                };

                await Task.WhenAll(warmupTasks);

                _logger.LogInformation("缓存预热完成");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "缓存预热失败");
            }
        }

        private async Task WarmupWorkflowDataAsync()
        {
            try
            {
                // 暂时简化工作流预热
                _logger.LogInformation("工作流数据预热已简化");
                await Task.CompletedTask;
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "工作流数据预热失败");
            }
        }

        private async Task WarmupTemplateDataAsync()
        {
            try
            {
                // 暂时禁用模板预热，待 ITemplateAppService 接口完善后启用
                _logger.LogInformation("模板数据预热已暂时禁用");
                await Task.CompletedTask;
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "模板数据预热失败");
            }
        }

        private async Task WarmupConfigDataAsync()
        {
            try
            {
                // 预热系统配置
                await _cacheService.SetAsync("system:startup_time", DateTime.UtcNow, TimeSpan.FromHours(24));
                _logger.LogInformation("预热配置数据完成");
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "配置数据预热失败");
            }
        }

        private async Task WarmupUserDataAsync()
        {
            try
            {
                // 预热用户相关数据
                await _cacheService.SetAsync("users:active_count", 0, TimeSpan.FromMinutes(15));
                _logger.LogInformation("预热用户数据完成");
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "用户数据预热失败");
            }
        }
    }

    /// <summary>
    /// 缓存监控服务
    /// </summary>
    public class CacheMonitoringService
    {
        private readonly HybridCacheService _hybridCache;
        private readonly ILogger<CacheMonitoringService> _logger;
        private readonly Timer _monitoringTimer;

        public CacheMonitoringService(
            HybridCacheService hybridCache,
            ILogger<CacheMonitoringService> logger)
        {
            _hybridCache = hybridCache;
            _logger = logger;
            
            // 每分钟监控一次缓存状态
            _monitoringTimer = new Timer(MonitorCacheHealth, null, TimeSpan.Zero, TimeSpan.FromMinutes(1));
        }

    private void MonitorCacheHealth(object? state)
        {
            try
            {
                var stats = _hybridCache.GetStatistics();
                
                // 记录缓存统计
                _logger.LogInformation("缓存统计 - 命中率: {HitRate:P2}, 内存命中率: {MemoryHitRate:P2}, 总请求: {TotalRequests}",
                    stats.HitRate, stats.MemoryHitRate, stats.TotalRequests);

                // 检查缓存健康状态
                if (stats.HitRate < 0.7 && stats.TotalRequests > 1000)
                {
                    _logger.LogWarning("缓存命中率偏低: {HitRate:P2}", stats.HitRate);
                }

                if (stats.MemoryHitRate < 0.3 && stats.TotalRequests > 1000)
                {
                    _logger.LogWarning("内存缓存命中率偏低: {MemoryHitRate:P2}", stats.MemoryHitRate);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "缓存监控失败");
            }
        }

        public void Dispose()
        {
            _monitoringTimer?.Dispose();
        }
    }

    #region 配置和统计类

    /// <summary>
    /// 混合缓存配置选项
    /// </summary>
    public class HybridCacheOptions
    {
        /// <summary>
        /// 是否启用分布式缓存
        /// </summary>
        public bool EnableDistributedCache { get; set; } = true;

        /// <summary>
        /// 默认缓存过期时间
        /// </summary>
        public TimeSpan DefaultExpiry { get; set; } = TimeSpan.FromMinutes(30);

        /// <summary>
        /// 内存缓存最大过期时间
        /// </summary>
        public TimeSpan MemoryMaxExpiry { get; set; } = TimeSpan.FromMinutes(10);

        /// <summary>
        /// 内存缓存回写过期时间
        /// </summary>
        public TimeSpan MemoryBackfillExpiry { get; set; } = TimeSpan.FromMinutes(5);

        /// <summary>
        /// 内存缓存大小限制（字节）
        /// </summary>
        public long MemorySizeLimit { get; set; } = 100 * 1024 * 1024; // 100MB

        /// <summary>
        /// 缓存压缩阈值（字节）
        /// </summary>
        public int CompressionThreshold { get; set; } = 1024; // 1KB

        /// <summary>
        /// 是否启用缓存压缩
        /// </summary>
        public bool EnableCompression { get; set; } = true;
    }

    /// <summary>
    /// 缓存统计信息
    /// </summary>
    public class CacheStatistics
    {
        public long MemoryHits { get; set; }
        public long DistributedHits { get; set; }
        public long Misses { get; set; }
        public long TotalRequests { get; set; }
        public double HitRate { get; set; }
        public double MemoryHitRate { get; set; }
    }

    #endregion

    #region 服务注册扩展

    /// <summary>
    /// 增强缓存服务注册扩展
    /// </summary>
    public static class EnhancedCacheServiceCollectionExtensions
    {
        /// <summary>
        /// 添加增强缓存服务
        /// </summary>
        public static IServiceCollection AddEnhancedCache(this IServiceCollection services, IConfiguration config)
        {
            // 添加内存缓存
            services.AddMemoryCache(options =>
            {
                options.SizeLimit = config.GetValue<long>("Cache:Memory:SizeLimit", 100 * 1024 * 1024);
                options.CompactionPercentage = config.GetValue<double>("Cache:Memory:CompactionPercentage", 0.25);
            });

            // 配置混合缓存选项
            var hybridOptions = new HybridCacheOptions();
            config.GetSection("Cache:Hybrid").Bind(hybridOptions);
            services.AddSingleton(hybridOptions);

            // 添加分布式缓存服务（基于配置）
            var cacheType = config["Cache:Type"]?.ToLower() ?? "memory";
            switch (cacheType)
            {
                case "redis":
                    services.AddStackExchangeRedisCache(options =>
                    {
                        options.Configuration = config.GetConnectionString("Redis");
                    });
                    services.AddSingleton<ICacheService>(provider =>
                        new RedisCacheService(
                            provider.GetRequiredService<IConnectionMultiplexer>(),
                            provider.GetRequiredService<ILogger<RedisCacheService>>()));
                    break;
                
                case "memory":
                default:
                    services.AddSingleton<ICacheService>(provider =>
                        new CacheService(
                            provider.GetRequiredService<IMemoryCache>(),
                            provider.GetRequiredService<IConfiguration>()));
                    break;
            }

            // 添加混合缓存服务
            services.AddSingleton<HybridCacheService>();
            
            // 添加缓存预热服务
            services.AddSingleton<CacheWarmupService>();
            
            // 添加缓存监控服务
            services.AddSingleton<CacheMonitoringService>();

            return services;
        }

        /// <summary>
        /// 添加缓存健康检查
        /// </summary>
        public static IServiceCollection AddCacheHealthChecks(this IServiceCollection services, IConfiguration config)
        {
            services.AddHealthChecks()
                .AddCheck<CacheHealthCheck>("cache", tags: new[] { "cache", "ready" });

            return services;
        }
    }

    /// <summary>
    /// 缓存健康检查
    /// </summary>
    public class CacheHealthCheck : Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck
    {
        private readonly ICacheService _cacheService;

        public CacheHealthCheck(ICacheService cacheService)
        {
            _cacheService = cacheService;
        }

        public async Task<Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult> CheckHealthAsync(
            Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckContext context,
            CancellationToken cancellationToken = default)
        {
            try
            {
                var testKey = "health_check_" + Guid.NewGuid();
                var testValue = DateTime.UtcNow;

                // 测试设置缓存
                await _cacheService.SetAsync(testKey, testValue, TimeSpan.FromSeconds(10));

                // 测试获取缓存
                var retrieved = await _cacheService.GetAsync<DateTime>(testKey);

                // 测试移除缓存
                await _cacheService.RemoveAsync(testKey);

                if (retrieved == testValue)
                {
                    return Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult.Healthy("缓存服务正常");
                }
                else
                {
                    return Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult.Degraded("缓存数据不一致");
                }
            }
            catch (Exception ex)
            {
                return Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult.Unhealthy("缓存服务异常", ex);
            }
        }
    }

    #endregion
}
